package com.aurora.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aurora.entity.Baidu;
import com.aurora.mapper.BaiduDao;
import com.aurora.model.vo.Result;
import com.aurora.service.BaiduService;
import com.aurora.utils.Hex2StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * <p>(Baidu)表服务实现类
 *
 * @author makejava
 * @since 2022-10-21 09:11:49
 */
@Service("baiduService")
public class BaiduServiceImpl extends ServiceImpl<BaiduDao, Baidu> implements BaiduService {

    /**
     * pageSize
     */
    private static final Integer PAGE_SIZE = 100;
    public static final String ERRNO = "errno";
    public static final String STRING = "0";
    public static final String CALL_BACK = "http://101.35.180.115:19004/baidu/callBack";
    /**
     * 发起授权码连接
     */
    private final String LOGIN_URL = "https://openapi.baidu.com/oauth/2.0/";

    /**
     * 用户信息 接口
     */
    private final String USER_URL = "https://pan.baidu.com/rest/2.0/xpan/";

    /**
     * appId
     */
    private final String APP_ID = "27997582";
    /**
     * App key
     */
    private final String APP_KEY = "YwYuQs8bcEG0P1RvqgqSlHWjgiECF3Gu";

    /**
     * Secret key
     */
    private final String SECRET_KEY = "doOdsazdHLRoy67EZ6mQK51nZtArWCFh";

    /**
     * Sign key
     */
    private final String SIGN_KEY = "7UolN8nSZU!LPLTmP6uRY^xDLnCOTCL8";

    /**
     * 请求授权码 百度登录接口
     *
     * @return String 授权码
     */
    @Override
    public String login() {
        //请求参数
        Map<String, Object> param = MapUtil.builder(new HashMap<String, Object>(8))
                .put("response_type", "code")
                .put("client_id", APP_KEY)
                .put("redirect_uri", CALL_BACK)
                .put("scope", "basic,netdisk")
                .put("device_id", APP_ID)
                .put("display", "page")
                .put("qrcode", "1").build();
        //Map转 url参数
        return LOGIN_URL + "authorize?" + MapUtil.join(param, "&", "=");
    }

    /**
     * 回调接口
     *
     * @param code 授权码
     * @return CommonResult
     * @throws UnsupportedEncodingException 异常
     */
    @Override
    public Result<?> callBack(String code) throws UnsupportedEncodingException {
        //请求参数
        Map<String, Object> param = MapUtil.builder(new HashMap<String, Object>(8))
                .put("grant_type", "authorization_code")
                .put("code", code)
                .put("client_id", APP_KEY)
                .put("client_secret", SECRET_KEY)
                .put("force_login", 1)
                .put("redirect_uri", CALL_BACK).build();
        //拼接
        String reqUrl = LOGIN_URL + "token?" + MapUtil.join(param, "&", "=");
        //请求
        String result = HttpUtil.get(reqUrl, CharsetUtil.CHARSET_UTF_8);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        //用于刷新 Access Token, 有效期为10年。
        String refreshToken = "";
        try {
            refreshToken = jsonObject.get("refresh_token").toString();

        } catch (Exception e) {
            return Result.fail("授权失败");
        }
        //请求用户信息
        Baidu umsBaidu = reqUserInfo(refreshToken);
        return StringUtils.isBlank(umsBaidu.getBaiduName()) ? Result.ok("登录失败") : Result.ok("登录成功");
    }

    /**
     * 请求用户信息
     *
     * @param refreshToken 用于刷新Access Token, 有效期为10年。
     */
    public Baidu reqUserInfo(String refreshToken) throws UnsupportedEncodingException {
        JSONObject refreshObject = refreshToken(refreshToken);
        //请求参数
        Map<String, Object> param = MapUtil.builder(new HashMap<String, Object>(8))
                .put("method", "uinfo")
                .put("access_token", refreshObject.get("access_token")).build();
        //拼接

        String reqUrl = USER_URL + "nas?" + MapUtil.join(param, "&", "=");
        String result = HttpUtil.get(reqUrl);

        JSONObject jsonObject = JSONUtil.parseObj(result);
        if (!STRING.equals(jsonObject.get(ERRNO).toString())) {
            return new Baidu();
        }
        //创建百度用户对象
        Baidu umsBaidu = new Baidu();
        umsBaidu.setBaiduName(jsonObject.get("baidu_name").toString());
        umsBaidu.setNetdiskName(jsonObject.get("netdisk_name").toString());
        umsBaidu.setAvatarUrl(jsonObject.get("avatar_url").toString());
        umsBaidu.setVipType(Integer.parseInt(jsonObject.get("vip_type").toString()));
        umsBaidu.setUk(jsonObject.get("uk").toString());
        umsBaidu.setAcessToken(refreshObject.get("access_token").toString());
        umsBaidu.setExpiresIn(Integer.parseInt(refreshObject.get("expires_in").toString()));
        umsBaidu.setRefreshToken(refreshObject.get("refresh_token").toString());
        umsBaidu.setScope(Hex2StrUtil.hex2UTF8(refreshObject.get("scope").toString()));
        //判断数据库中是否存在该用户
        Baidu baidu = getOne(new LambdaQueryWrapper<Baidu>().eq(Baidu::getUk, umsBaidu.getUk()));
        if (Objects.isNull(baidu)) {
            this.save(umsBaidu);
        } else {
            umsBaidu.setId(baidu.getId());
            this.updateById(umsBaidu);
        }

        return umsBaidu;
    }


    /**
     * 刷新token
     */
    public JSONObject refreshToken(String refreshToken) {
        //请求参数
        Map<String, Object> params = MapUtil.builder(new HashMap<String, Object>(8))
                .put("grant_type", "refresh_token")
                .put("refresh_token", refreshToken)
                .put("client_id", APP_KEY)
                .put("client_secret", SECRET_KEY).build();
        //拼接
        String reqUrl = LOGIN_URL + "token?" + MapUtil.join(params, "&", "=");
        //请求
        String result = HttpUtil.get(reqUrl, CharsetUtil.CHARSET_UTF_8);
        return JSONUtil.parseObj(result);
    }


    /**
     * 获取百度文件列表
     *
     * @param id   路径
     * @param page 页码
     * @return 文件列表
     */
    @Override
    public Result<?> fileList(String id, String page) {

        //请求参数
        Map<String, Object> params = MapUtil.builder(new HashMap<String, Object>(8))
                .put("method", "list")
                .put("access_token", getAccessToken(id))
                .put("start", (Integer.parseInt(page) - 1) * PAGE_SIZE)
                .put("limit", Integer.parseInt(page) * PAGE_SIZE)
                .put("web", 1)
                .put("showempty", 0)
                .build();
        //拼接
        String reqUrl = USER_URL + "file?" + MapUtil.join(params, "&", "=");
        //请求
        String result = HttpUtil.get(reqUrl, CharsetUtil.CHARSET_UTF_8);
        return Result.ok(JSONUtil.parseObj(result));
    }

    /**
     * 获取百度文件图片列表
     *
     * @param id   路径
     * @param page 页码
     * @return 文件列表
     */
    @Override
    public Result<?> photoList(String id, String page) {

        //请求参数
        Map<String, Object> params = MapUtil.builder(new HashMap<String, Object>(8))
                .put("method", "imagelist")
                .put("access_token", getAccessToken(id))
                .put("page", page)
                .put("num", PAGE_SIZE)
                .put("web", 0)
                .put("recursion", 1)
                .build();
        //拼接
        String reqUrl = USER_URL + "file?" + MapUtil.join(params, "&", "=");
        //请求
        String result = HttpUtil.get(reqUrl, CharsetUtil.CHARSET_UTF_8);
        return Result.ok(JSONUtil.parseObj(result));
    }

    /**
     * 通过ID得到access_token
     *
     * @param id 百度表的id
     */
    private String getAccessToken(String id) {
        Baidu baidu = this.getById(id);
        return baidu.getAcessToken();
    }

    /**
     * refreshTokenC
     *
     * @param id 路用户id径
     * @return success
     */
    @Override
    public Result<?> refreshTokenC(String id) throws UnsupportedEncodingException {
        Baidu baidu = this.getById(id);
        return Result.ok(reqUserInfo(baidu.getRefreshToken()));
    }
}

